﻿using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace ThreeDWorld
{
    public class Map : IDisposable
    {
        private Texture2D[] _Textures1;
        private Texture2D[] _Textures2;
        private VertexBuffer[] _VertexBuffers;
        private IndexBuffer[] _IndexBuffers;

        public Map(ContentReader reader)
        {
            Game = reader.Content.Game;

            BatchCount = reader.ReadInt32();

            _Textures1 = new Texture2D[BatchCount];
            _Textures2 = new Texture2D[BatchCount];
            _VertexBuffers = new VertexBuffer[BatchCount];
            _IndexBuffers = new IndexBuffer[BatchCount];

            for (int i = 0; i != BatchCount; i++)
            {
                _Textures1[i] = reader.ReadExternalReference<Texture2D>();

                if (reader.ReadBoolean())
                {
                    _Textures2[i] = reader.ReadExternalReference<Texture2D>();
                }
                else
                {
                    _Textures2[i] = null;
                }

                _VertexBuffers[i] = reader.ReadVertexBuffer();
                _IndexBuffers[i] = reader.ReadIndexBuffer();
            }

            Primitives = new Primitive[reader.ReadInt32()];

            for (int i = 0; i != Primitives.Length; i++)
            {
                Primitives[i] = new Primitive(reader);
            }
        }

        public Game Game
        {
            get;
            private set;
        }

        public GraphicsDevice GraphicsDevice
        {
            get { return Game.GraphicsDevice; }
        }

        public int BatchCount
        {
            get;
            private set;
        }

        public Primitive[] Primitives
        {
            get;
            private set;
        }

        public bool BatchIsDualTextured(int index)
        {
            return _Textures2[index] != null;
        }

        public void DrawBatch(int index)
        {
            VertexBuffer vertexBuffer = _VertexBuffers[index];
            IndexBuffer indexBuffer = _IndexBuffers[index];

            GraphicsDevice.Textures[0] = _Textures1[index];
            GraphicsDevice.Textures[1] = _Textures2[index];

            try
            {
                GraphicsDevice.SetVertexBuffer(vertexBuffer);
                GraphicsDevice.Indices = indexBuffer;

                GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, vertexBuffer.VertexCount, 0, indexBuffer.IndexCount / 3);
            }
            finally
            {
                GraphicsDevice.SetVertexBuffer(null);
                GraphicsDevice.Indices = null;
            }
        }

        public void Dispose()
        {
            for (int i = 0; i != BatchCount; i++)
            {
                VertexBuffer vertexBuffer = _VertexBuffers[i];
                IndexBuffer indexBuffer = _IndexBuffers[i];

                if (!vertexBuffer.IsDisposed)
                {
                    vertexBuffer.Dispose();
                }
                if (!indexBuffer.IsDisposed)
                {
                    indexBuffer.Dispose();
                }
            }
        }
    }
}
